// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#pragma once

#include <pollux/type/type.h>

namespace kumo::pollux {

    // TODO: move cppToType testing utilities.
    template<typename T>
    struct CppToType {
    };

    template<TypeKind KIND>
    struct CppToTypeBase : public TypeTraits<KIND> {
        static auto create() {
            return TypeFactory<KIND>::create();
        }
    };

    template<>
    struct CppToType<int128_t> : public CppToTypeBase<TypeKind::HUGEINT> {
    };

    template<>
    struct CppToType<__uint128_t> : public CppToTypeBase<TypeKind::HUGEINT> {
    };

    template<>
    struct CppToType<int64_t> : public CppToTypeBase<TypeKind::BIGINT> {
    };

    template<>
    struct CppToType<uint64_t> : public CppToTypeBase<TypeKind::BIGINT> {
    };

    template<>
    struct CppToType<int32_t> : public CppToTypeBase<TypeKind::INTEGER> {
    };

    template<>
    struct CppToType<uint32_t> : public CppToTypeBase<TypeKind::INTEGER> {
    };

    template<>
    struct CppToType<int16_t> : public CppToTypeBase<TypeKind::SMALLINT> {
    };

    template<>
    struct CppToType<uint16_t> : public CppToTypeBase<TypeKind::SMALLINT> {
    };

    template<>
    struct CppToType<int8_t> : public CppToTypeBase<TypeKind::TINYINT> {
    };

    template<>
    struct CppToType<uint8_t> : public CppToTypeBase<TypeKind::TINYINT> {
    };

    template<>
    struct CppToType<bool> : public CppToTypeBase<TypeKind::BOOLEAN> {
    };

    template<>
    struct CppToType<melon::StringPiece> : public CppToTypeBase<TypeKind::VARCHAR> {
    };

    template<>
    struct CppToType<pollux::StringView> : public CppToTypeBase<TypeKind::VARCHAR> {
    };

    template<>
    struct CppToType<std::string_view> : public CppToTypeBase<TypeKind::VARCHAR> {
    };

    template<>
    struct CppToType<std::string> : public CppToTypeBase<TypeKind::VARCHAR> {
    };

    template<>
    struct CppToType<const char *> : public CppToTypeBase<TypeKind::VARCHAR> {
    };

    template<>
    struct CppToType<melon::ByteRange> : public CppToTypeBase<TypeKind::VARBINARY> {
    };

    template<>
    struct CppToType<float> : public CppToTypeBase<TypeKind::REAL> {
    };

    template<>
    struct CppToType<double> : public CppToTypeBase<TypeKind::DOUBLE> {
    };

    template<>
    struct CppToType<Timestamp> : public CppToTypeBase<TypeKind::TIMESTAMP> {
    };

    // TODO: maybe do something smarter than just matching any shared_ptr, e.g. we
    // can declare "registered" types explicitly
    template<typename T>
    struct CppToType<std::shared_ptr<T> > : public CppToTypeBase<TypeKind::OPAQUE> {
        // We override the type with the concrete specialization here!
        // using NativeType = std::shared_ptr<T>;
        static auto create() {
            return OpaqueType::create<T>();
        }
    };

    template<>
    struct CppToType<UnknownValue> : public CppToTypeBase<TypeKind::UNKNOWN> {
    };

    // todo: remaining cpp2type
} // namespace kumo::pollux
